﻿// Copyright richyp 2009
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Richyp.Bodger;

namespace Richyp.Bodger.UI {
    public partial class QuantityWargearControl : UserControl {
        private TabPage page = null;
        public QuantityWargearControl(TabPage page) {
            InitializeComponent();
            this.page = page;
            this.SetStyle(ControlStyles.SupportsTransparentBackColor| ControlStyles.OptimizedDoubleBuffer, true);
        }
        
        private ListEntry entry = null;
        public ListEntry Entry {
            get {
                return this.entry;
            }
        }

        private Wargear wargear;
        public Wargear Wargear { 
            get { 
                return this.wargear; 
            } 
        }

        private string unitName = null;

        private List<Unit> units = new List<Unit>();
        private Equipment equipmentEntry = null;
        private bool populating = false;

        public void Populate(string unitName, ListEntry entry, Wargear wargear) {
            this.populating = true;
            this.unitName = unitName;
            this.entry = entry;
            this.wargear = wargear;

            this.labelWargear.Text = wargear.Name;
            ToolTip tip = new ToolTip();
            tip.SetToolTip(this.labelWargear, wargear.Description);
            this.units.Clear();
       
            foreach (Unit unit in this.entry.Units) {
                if (unit.Name.ToUpper() == unitName.ToUpper()) {
                    units.Add(unit);
                }
            }
            if (units.Count == 0) {
                throw new Exception("Failed to find any units");
            }
            foreach (Equipment equipment in units[0].AllWargear) {
                if (equipment.Wargear.Name == wargear.Name) {
                    equipmentEntry = equipment;
                    break;
                }                
            }            
            if (equipmentEntry == null) {
                throw new Exception("Failed to find equipment entry in unit: " + units[0].Name + " for " + wargear.Name);
            }
            
            this.labelCost.Text = equipmentEntry.Cost.ToString();
            this.buttonAdd.Enabled = !equipmentEntry.Fixed;
            int current = 0;
            foreach (Unit unit in units) {
                foreach (Equipment equipped in unit.Equipped) {
                    if (equipped.Wargear.Name == equipmentEntry.Wargear.Name) {
                        current++;
                    }
                }
            }
            this.labelQty.Text = current.ToString();
            oldValue = current;
           
            bool allowed = true;
            bool found = false;
            bool replacement = false;
            int qty = int.Parse(this.labelQty.Text);
            if (qty >= this.equipmentEntry.MaximumPerSquad || qty >= this.units.Count) {
                allowed = false;
            }

            foreach (ReplacementGroup group in units[0].ReplacementGroups) {
                if (group.Default.Wargear.Name == this.wargear.Name) {
                    replacement = true;
                    break;
                }                
            }
            if (allowed) {
                foreach (ReplacementGroup group in units[0].ReplacementGroups) {
                    foreach (DistinctEntry dentry in group.DistinctEntries) {
                        foreach (Equipment deq in dentry.Options) {
                            if (deq.Wargear.Name == this.wargear.Name) {
                                allowed = this.units.Count >= dentry.Requires;                                
                                if (qty >= deq.MaximumPerSquad || qty >= this.units.Count || qty >= dentry.Maximum) {
                                    allowed = false;
                                }
                                found = true;
                                break;
                            }
                        }
                        if (found) {
                            break;
                        }
                    }
                    if (found) {
                        break;
                    }
                }
            }
            if (!allowed) {
                this.labelWargear.ForeColor = Color.DarkGray;
            } else {
                this.labelWargear.ForeColor = Color.Black;
            }
            this.populating = false;
            this.buttonAdd.Enabled = allowed;
            this.buttonRemove.Enabled = current > 0;

            if( replacement ) {
                this.buttonRemove.Enabled = false;
            }
        }

        public int Quantity {
            get {
                return int.Parse(this.labelQty.Text);
            }
            set {
                this.labelQty.Text = value.ToString();
            }
        }

        private int oldValue = 0;


        public void Add() {
            if (!populating) {
                int qty = int.Parse(this.labelQty.Text);
                // Decreased
                if (oldValue > qty+1) {

                } else if (oldValue < qty+1 && 
                    qty+1 <= this.units.Count &&
                    qty+1 <= this.equipmentEntry.MaximumPerSquad) {
                    // Increased
                    qty++;
                    Unit unit = this.entry.GetUnitByName(unitName);
                    ReplacementGroup replacementOption = null;
                    bool isDefault = false;
                    DistinctEntry distinct = null;
                    Equipment replacementEquipment = null;
                    foreach (ReplacementGroup group in unit.ReplacementGroups) {
                        if (group.Default.Wargear.Name.ToUpper() == this.wargear.Name.ToUpper()) {
                            // Default item in a replacement group has been clicked
                            isDefault = true;
                            replacementOption = group;
                            break;
                        }
                        foreach (Equipment eq in group.Options) {
                            if (eq.Wargear.Name.ToUpper() == this.wargear.Name.ToUpper()) {
                                // Member of a replacement group has been clicked
                                replacementOption = group;
                                break;
                            }
                        }
                        foreach (DistinctEntry entry in group.DistinctEntries) {
                            foreach (Equipment eq in entry.Options) {
                                if (eq.Wargear.Name.ToUpper() == this.wargear.Name.ToUpper()) {
                                    // Distinct option has been clicked
                                    replacementOption = group;
                                    replacementEquipment = eq;
                                    distinct = entry;
                                    break;
                                }
                            }
                        }
                        if (replacementOption != null) {
                            break;
                        }
                    }
                    if (replacementOption != null) {
                        if (isDefault) {
                            Equipment removeItem = null;
                            Unit removeFrom = null;
                            foreach (Unit unitEntry in this.units) {
                                foreach (Equipment equipment in replacementOption.GetAllOptions()) {
                                    if (equipment.Wargear.Name.ToUpper() != this.wargear.Name.ToUpper()) {
                                        foreach (Equipment replacement in unitEntry.Equipped) {
                                            if (equipment.Wargear.Name.ToUpper() ==
                                                replacement.Wargear.Name.ToUpper()) {
                                                removeItem = replacement;
                                                removeFrom = unitEntry;
                                                break;
                                            }
                                        }
                                        if (removeItem != null) {
                                            break;
                                        }
                                    }
                                }
                                if (removeItem != null) {
                                    break;
                                }
                            }

                            if (removeFrom == null) {
                                foreach (Unit unitEntry in this.units) {
                                    foreach (DistinctEntry d in replacementOption.DistinctEntries) {
                                        foreach (Equipment eq in d.Options) {
                                            foreach (Equipment eq2 in unitEntry.Equipped) {
                                                if (eq2.Wargear.Name == eq.Wargear.Name && eq.Wargear.Name != this.wargear.Name) {
                                                    removeFrom = unitEntry;
                                                    removeItem = eq2;
                                                    break;
                                                }
                                            }
                                            if (removeItem != null) {
                                                break;
                                            }
                                        }
                                        if (removeItem != null) {
                                            break;
                                        }
                                    }
                                    if (removeItem != null) {
                                        break;
                                    }
                                }
                            }
                            if (removeItem != null) {
                                removeFrom.Equipped.Remove(removeItem);
                                removeFrom.Equipped.Add(this.equipmentEntry);
                            }
                        } else { // Not default
                            if (replacementEquipment != null) {
                                int count = 0;
                                foreach (Unit u in units) {
                                    foreach (Equipment eq in u.Equipped) {
                                        if (eq.Wargear.Name.ToUpper() == replacementEquipment.Wargear.Name.ToUpper()) {
                                            count++;
                                        }
                                    }
                                }
                                if (count >= replacementEquipment.MaximumPerSquad || count >= units.Count) {
                                    return;
                                }

                                if (distinct != null) {
                                    Equipment removeItem = null;
                                    Unit removeFrom = null;
                                    List<ReplacementEntry> alternatives = new List<ReplacementEntry>();
                                    if (distinct.Requires <= this.units.Count) {
                                        foreach (Unit u in units) {
                                            foreach (Equipment eq in u.Equipped) {
                                                foreach (Equipment option in distinct.Options) {
                                                    if (option.Wargear.Name == eq.Wargear.Name && option.Wargear.Name != this.wargear.Name) {
                                                        removeFrom = u;
                                                        removeItem = eq;
                                                        break;
                                                    }
                                                }
                                                if (removeItem != null) {
                                                    break;
                                                } else {
                                                    if (eq.Wargear.Name == replacementOption.Default.Wargear.Name) {
                                                        removeFrom = u;
                                                        removeItem = eq;
                                                        ReplacementEntry entry = new ReplacementEntry();
                                                        entry.Unit = u;
                                                        entry.Equipment = eq;
                                                        alternatives.Add(entry);
                                                    }
                                                    foreach (Equipment eq2 in replacementOption.Alternatives) {
                                                        if (eq.Wargear.Name == eq2.Wargear.Name) {
                                                            ReplacementEntry entry = new ReplacementEntry();
                                                            entry.Unit = u;
                                                            entry.Equipment = eq;
                                                            alternatives.Add(entry);
                                                        }
                                                    }
                                                }
                                            }
                                            if (removeItem != null) {
                                                break;
                                            }
                                        }
                                        if (removeItem == null) {
                                            foreach (Unit u in units) {
                                                foreach (Equipment eq in u.Equipped) {
                                                    foreach (Equipment option in replacementOption.Options) {
                                                        if (eq.Wargear.Name == option.Wargear.Name && eq.Wargear.Name != this.wargear.Name) {
                                                            removeFrom = u;
                                                            removeItem = eq;
                                                            break;
                                                        }
                                                    }
                                                    if (removeItem != null) {
                                                        break;
                                                    }
                                                }
                                                if (removeItem != null) {
                                                    break;
                                                }
                                            }
                                        }

                                    }
                                    Unit addTo = removeFrom;
                                    if (alternatives.Count > 1) {
                                        Console.WriteLine("alternatives found");
                                        OptionDialog options = new OptionDialog();
                                        options.Populate(replacementOption.Default, alternatives);
                                        DialogResult dr = options.ShowDialog(this);
                                        if (dr == DialogResult.OK) {
                                            removeFrom = options.Chosen.Unit;
                                            removeItem = options.Chosen.Equipment;
                                        } else {
                                            return;
                                        }
                                    }
                                    if (removeFrom != null) {
                                        removeFrom.Equipped.Remove(removeItem);
                                    }
                                    if (addTo == null) {
                                        addTo = units[0];
                                    }
                                    addTo.Equipped.Add(this.equipmentEntry);

                                }
                            } else { // no replacement 
                                Unit removeFrom = null;
                                Equipment removeItem = null;
                                foreach (Unit u in this.units) {
                                    foreach (Equipment eq in u.Equipped) {
                                        if (eq.Wargear.Name == replacementOption.Default.Wargear.Name) {
                                            removeFrom = u;
                                            removeItem = eq;
                                            break;
                                        }
                                    }
                                    if (removeItem != null) {
                                        break;
                                    }
                                }

                                if (removeItem == null) {
                                    foreach (Unit u in this.units) {
                                        foreach (Equipment eq in u.Equipped) {
                                            foreach (Equipment option in replacementOption.Options) {
                                                if (option.Wargear.Name == eq.Wargear.Name && eq.Wargear.Name != this.wargear.Name) {
                                                    removeItem = eq;
                                                    removeFrom = u;
                                                    break;
                                                }
                                            }
                                            foreach (DistinctEntry d in replacementOption.DistinctEntries) {
                                                foreach (Equipment eq2 in d.Options) {
                                                    if (eq.Wargear.Name == eq2.Wargear.Name && eq.Wargear.Name != this.wargear.Name) {
                                                        removeFrom = u;
                                                        removeItem = eq;
                                                        break;
                                                    }
                                                    if (removeItem != null) {
                                                        break;
                                                    }
                                                }
                                                if (removeItem != null) {
                                                    break;
                                                }
                                            }
                                            foreach (Equipment eq2 in replacementOption.Alternatives) {
                                                if (eq2.Wargear.Name == eq.Wargear.Name && eq.Wargear.Name != this.wargear.Name) {
                                                    removeItem = eq;
                                                    removeFrom = u;
                                                    break;
                                                }
                                            }
                                            if (removeItem != null) {
                                                break;
                                            }
                                        }
                                        if (removeItem != null) {
                                            break;
                                        }
                                    }
                                }

                                if (removeFrom == null) {
                                    //OOOOOPPPS
                                    Console.WriteLine("Something bad happened");
                                } else {
                                    removeFrom.Equipped.Remove(removeItem);
                                    removeFrom.Equipped.Add(this.equipmentEntry);
                                    if (this.equipmentEntry.Removes != null && this.equipmentEntry.Removes.Length > 0) {
                                        string[] items = this.equipmentEntry.Removes.Split(new char[] { ',' });
                                        List<Equipment> remove = new List<Equipment>();
                                        foreach (string item in items) {                                            
                                            foreach (Equipment eq in removeFrom.Equipped) {
                                                if (eq.Wargear.Name.ToUpper() == item.ToUpper()) {
                                                    remove.Add(eq);
                                                }
                                            }
                                        }
                                        foreach (Equipment eq in remove) {
                                            removeFrom.Equipped.Remove(eq);
                                        }
                                    }
                                }
                            }
                        }
                    } else { // Not a replacement item
                        Unit addMe = null;
                        int count = 0;
                        foreach (Unit u in this.units) {
                            bool exists = false;
                            foreach (Equipment eq in u.Equipped) {
                                if (eq.Wargear.Name == this.wargear.Name) {
                                    exists = true;
                                    count++;
                                }
                            }
                            if (!exists) {
                                addMe = u;
                            }
                        }
                        if (addMe != null) {
                            if( count < this.units.Count ) {
                                if (count < this.equipmentEntry.MaximumPerSquad) {
                                    addMe.Equipped.Add(this.equipmentEntry);
                                }
                            }
                        }
                    }
                    foreach (Control control in this.page.Controls) {
                        if (control is QuantityWargearControl) {
                            ((QuantityWargearControl)control).Refresh();
                        } else if (control is ToggleWargearControl) {
                            ((ToggleWargearControl)control).Populate();
                        }
                    }
                }
                oldValue = qty;
                this.entry.UpdateRow();
            }
        }

        public void Remove() {
            bool isReplacementGroupEntry = false;
            ReplacementGroup replacementGroup = null;
            foreach (ReplacementGroup group in this.units[0].ReplacementGroups) {
                foreach (Equipment eq2 in group.GetAllOptions()) {
                    if (eq2.Wargear.Name == this.wargear.Name) {
                        isReplacementGroupEntry = true;
                        replacementGroup = group;
                        break;
                    }
                }
                if (isReplacementGroupEntry) {
                    break;
                }
            }

            // Remove first occurance
            Unit removeFrom = null;
            Equipment removeItem = null;
            foreach (Unit unit in this.units) {
                foreach (Equipment eq in unit.Equipped) {
                    if (eq.Wargear.Name == this.wargear.Name) {
                        removeFrom = unit;
                        removeItem = eq;
                        break;
                    }
                }
                if (removeItem != null) {
                    break;
                }
            }

            if (removeItem != null) {
                removeFrom.Equipped.Remove(removeItem);
            }

            if (isReplacementGroupEntry) {
                Equipment defaultItem = replacementGroup.Default;
                removeFrom.Equipped.Add(defaultItem);
            }

            foreach (Control control in this.page.Controls) {
                if (control is QuantityWargearControl) {
                    ((QuantityWargearControl)control).Refresh();
                }
            }
            this.entry.UpdateRow();
        }

        public override void Refresh() {
            this.Populate(this.unitName, this.entry, this.wargear);
        }

        private void buttonAdd_Click(object sender, EventArgs e) {
            this.Add();
        }

        private void buttonRemove_Click(object sender, EventArgs e) {
            this.Remove();
        }
    }

    public class ReplacementEntry {
        public Unit Unit;
        public Equipment Equipment;
    }
}
